home *** CD-ROM | disk | FTP | other *** search
- /*
- ***********************************************************************
- *
- * FlightView
- * A particular version of a generic ThreeDView optimized to flight through
- * "periodic" clouds
- *
- * Drawing the sky
- * For the sky, we use the same image (only viewed "upside down") and project
- * it using the formulas in view_3d.cc. The only trick is that we assume that
- * the sky is _very high above_, that is, the distance from the observer to
- * the sky is much bigger compared to the relative size (elevation) of separate
- * cloud "particles"
- *
- * We will start the derivation from the projection formulas of "view_3d.cc"
- * that project a point (x,y,z) of an elevation map onto
- *
- * u = beta/d(A) * (-gy*(x-xe) + gx*(y-ye))/|g| + Ou
- * v = beta/d(A) * (z-ze) + Ov
- * d(A) = (gx*(x-xe) + gy*(y-ye))/|g|
- * point on the screen. Let's lose some of the generality and require that
- * the gaze be strictly forward, that is, gx = 0 and gy = |g|. This simplifies
- * the formulas to
- * u = Ou - beta/d * (x-xe)
- * v = Ov + beta/d * (z-ze)
- * d = y - ye
- * Note that ze-z is the distance from a particular point on the elevation map
- * to the observer. Since the observer is far below, the elevation z of a
- * point on the map doesn't matter too much, so it can be assumed that
- * ze-z = const (which we called Zc). That simplifies fromulas to
- * u = Ou - beta/d * (x-xe)
- * v = Ov - beta/d * Zc
- * d = y - ye
- * To show that the sky is "above" us (as opposite to the elevation map which
- * is "below") we flip the sign in the formula for v:
- * v = Ov + beta/d * Zc
- * Thus v = Ov when d = infinity, and increases (towards the top edge of the
- * screen port) when d, the depth, decreases. Ov is the really horizon then.
- * The formulas above are easily invertible:
- * d = (Zc*beta)/(v-Ov)
- * y = d + ye
- * x = xe + (Ou-u)*d/beta
- * Thus, given a scanline with v > Ov, we scan it from u=0 through u=umax and
- * assign each pixel (u,v) the color off the elevation's map point
- * x = xe + Ou*Zc/(v-Ov) - u*Zc/(v-Ov)
- * y = ye + beta*Zc/(v-Ov)
- * Note that y does not actually depend on u.
- * We can choose parameter Zc so that the at the point right "above" us, that
- * is, at the top edge of the screen v=vmax, the increment in x we move to the next
- * scan point be exactly one. That means, Zc = vmax-Ov. Parameter beta above is
- * arbitrary as well (it doesn't have to be the same as the one used in 3D projection).
- * So, we'll choose it to be, say, 1/2.
- *
- ***********************************************************************
- */
-
- #include "FlightWindow.h"
- #include "view_3d.cc"
-
- // Quickly computes x % n, that is, adds or subtracts n until
- // the result (x) falls within [0,n-1]
- // We assume that x hasn't fall too far out of this interval to start
- // with
- static inline int fast_mod(int x, const int n)
- {
- while( x < 0 )
- x += n;
- while( x >= n )
- x -= n;
- return x;
- }
-
- class ThreeDProjector_PeriodicMap : public ThreeDProjectorCached
- {
- public:
- ThreeDProjector_PeriodicMap(const ElevationMap& _map, const ViewerPosition& viewer_pos,
- const ProjectionParameters& projp)
- : ThreeDProjectorCached(_map,viewer_pos,projp) {}
-
- inline void operator () (ThreeDViewBase::OneViewScanline::ScanPoint& point)
- {
- xu = fast_mod(xu,map_width_u);
- yu = fast_mod(yu,map_height_u);
- ThreeDProjectorCached::operator ()(point);
- }
- };
-
-
- // Draw the sky (as a background image)
- void FlightView::prepaint(void)
- {
- #if 1
- PixMapHandle pixmap = get_pixmap();
- const int bytes_per_row = OffScreenBuffer::bytes_per_row();
- const int nrows = height();
- assert( LockPixels(pixmap) );
- unsigned char * pixels_ptr = (unsigned char *)GetPixBaseAddr(pixmap);
- const int background_pixel = 0; // Clear the canvas before we start drawing
- const int scan_width = width();
- register unsigned char * rp = pixels_ptr;
- for(register int i=0; i < nrows; i++, rp += bytes_per_row)
- memset(rp,background_pixel,scan_width);
- UnlockPixels(pixmap);
- #else
- clear();
- #endif
- }
-
-
- // Force compilation of the template
- template class ThreeDView<ThreeDProjector_PeriodicMap>;
-